package com.chuangke.security.provider;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.chuangke.common.exception.ChuangkeException;
import com.chuangke.common.utils.PasswordEncoder;
import com.chuangke.login.config.LoginConfig;
import com.chuangke.security.authentication.CommonAuthenticatioToken;
import com.chuangke.security.authentication.UserPassAuthenticatioToken;
import com.chuangke.security.userdetails.JwtUserDetails;
import com.google.code.kaptcha.Constants;

/**
 * 身份验证提供者
 *
 * @author chuangke
 * @date Nov 20, 2018
 */
@Component("commonAuthenticationProvider")
public class UserPassAuthenticationProvider implements AuthenticationProvider {
	
	private static final Logger logger = LoggerFactory.getLogger(UserPassAuthenticationProvider.class);

	@Autowired
	private LoginConfig loginConfig ;
	@Autowired
	private UserDetailsService userDetailsService;

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		UserPassAuthenticatioToken catoken = (UserPassAuthenticatioToken) authentication;

		validateCaptcha(catoken) ;
		
		// 用户名密码校验
		String username = (String) catoken.getPrincipal();
		String password = (String) catoken.getCredentials();

		if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
			throw new BadCredentialsException("用户名或密码不能为空");
		}
		if (StringUtils.isBlank(password)) {
			throw new BadCredentialsException("登录失败，用户名或密码错误");
		}
		
		JwtUserDetails userDetails = null ;
		try {
			logger.info("************************username:{}",username);
			logger.info("************************userDetailsService:{}",userDetailsService);
			userDetails = (JwtUserDetails) userDetailsService.loadUserByUsername(username);
		}catch(Exception e) {
			logger.info("*******************************************");
			logger.error(e.getMessage());
			throw new BadCredentialsException(e.getMessage());
		}
		
		if(userDetails == null) {
			throw new BadCredentialsException("登录失败，用户名或密码错误");
		}

		if (!new PasswordEncoder(userDetails.getSalt()).matches(userDetails.getPassword(), password)) {
			throw new BadCredentialsException("登录失败，用户名或密码错误");
		}

        return new CommonAuthenticatioToken(userDetails, null, userDetails.getAuthorities());
	}

	@Override
	public boolean supports(Class<?> authentication) {
		if(!loginConfig.isOpenPassLogin()) {
			return false ;
		}
		return UserPassAuthenticatioToken.class.isAssignableFrom(authentication);
	}

	private void validateCaptcha(UserPassAuthenticatioToken catoken) {
		if(!loginConfig.isOpenCaptcha()) {
			return ;
		}
		// 验证码校验
		String inputCaptcha = catoken.getCaptcha();

		Object captcha = catoken.getRequest().getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
		catoken.getRequest().getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);

		if (captcha == null) {
			throw new ChuangkeException("验证码已失效");
		}
		if (!captcha.equals(inputCaptcha)) {
			throw new ChuangkeException("验证码不正确");
		}
	}

}